home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_068 / mg1b / tty / amiga / menustack.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  334 lines

  1. /*
  2.  *  Simple menu package.  Needs lotsa work to handle some cases.
  3.  *
  4.  *  Copyright 1985
  5.  *  Louis A. Mamakos
  6.  *  Software & Stuff
  7.  *  14813 Ashford Place
  8.  *  Laurel, MD  20707
  9.  *
  10.  *  For non-commerical use only.  This program, or any modifications, may not
  11.  *  be sold or incorporated into any product without prior permission from the
  12.  *  author.
  13.  *
  14.  *  Modified by mwm to handle "stacking" menus.
  15.  *    NB - adding item to a menu that's been "popped" back to doesn't work,
  16.  *    and probably never will.
  17.  *  Modified again by MPK to allow subitems again (non-stacking), and
  18.  *  fix bug when visiting files not in last menu.
  19.  */
  20.  
  21. #include <exec/types.h>
  22. #include <exec/nodes.h>
  23. #include <exec/lists.h>
  24. #include <exec/ports.h>
  25. #include <exec/devices.h>
  26. #include <exec/memory.h>
  27. #include <hardware/blit.h>
  28. #include <graphics/copper.h>
  29. #include <graphics/regions.h>
  30. #include <graphics/rastport.h>
  31. #include <graphics/gfxbase.h>
  32. #include <graphics/gels.h>
  33. #include <intuition/intuition.h>
  34.  
  35. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  36. #define    Menu_Clear    DisposeMenus    /* For ttyio.c    */
  37.  
  38. extern    char    *AllocMem();
  39. extern    char    *AllocRemember();
  40.  
  41. struct    Mem_Node {
  42.    struct Node mn_Node;
  43.    struct Remember mn_Memory;
  44.    struct Menu *mn_Menu;
  45.    } *Top, *RemHead();
  46.  
  47. extern struct NewWindow MicroEMACS ;    /* For Screen width & Height    */
  48. #define SCREENHEIGHT    (MicroEMACS . MaxHeight)
  49. #define SCREENWIDTH    (MicroEMACS . MaxWidth)
  50.  
  51. static struct List Memory;
  52. static int Cur_Menu, Cur_MenuItem, Cur_SubItem;
  53. static struct Menu *LastMenu;
  54. static struct MenuItem *LastMenuItem, *LastSubItem;
  55.  
  56. struct Menu *AutoMenu;      /* menu struct being dynamically built */
  57.  
  58. char *strsave();        /* Save a string in the remember list */
  59.  
  60. #ifdef LATTICE
  61. void
  62. #endif
  63. Menu_Init()
  64. {
  65.    Memory.lh_Head = (struct Node *) &(Memory.lh_Tail);
  66.    Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head);
  67.    Memory.lh_Tail = NULL;
  68.    Memory.lh_Type = NT_MEMORY;
  69.    Top = NULL;
  70.    Cur_Menu = Cur_MenuItem = Cur_SubItem = -1;
  71.    AutoMenu = LastMenu = NULL;     /* no menu chain yet */
  72.    LastMenuItem = LastSubItem = NULL;
  73. }
  74.  
  75. #ifdef LATTICE
  76. void
  77. #endif
  78. Menu_Clear()
  79. {
  80.  
  81.    while ((Top = RemHead(&Memory)) != NULL) {
  82.       FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  83.       FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  84.   }
  85.   Menu_Init();            /* Just for safeties sake */
  86. }
  87.  
  88. #ifdef LATTICE
  89. void
  90. #endif
  91. Menu_Pop()
  92. {
  93.  
  94.    if ((Top = RemHead(&Memory)) == NULL) return;
  95.    FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  96.    FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  97.    /* Now, set Top back to the real list head */
  98.    Top = (struct Mem_Node *) Memory.lh_Head;
  99.    LastMenu = Top->mn_Menu;
  100.    LastMenu->NextMenu = NULL;    /* Tie off the menu list */
  101.    LastMenuItem = NULL;        /* Wrong, but you can't add items here anyway */
  102.    LastSubItem = NULL;        /*    ditto                      */
  103.    Cur_Menu--;
  104. }
  105. /*
  106.  *  Add a MENU item.  Args are the text of the menu item, and an enable
  107.  *  flag.  Returns an Intuition type menu number, with the MenuItem and
  108.  *  Menu SubItem being NOITEM and NOSUB.  The MENUITEM part is valid.
  109.  */
  110. /* dummy Intuitext used to calculate length of menu names */
  111. static struct IntuiText itd = {
  112.    AUTOFRONTPEN, AUTOBACKPEN, JAM2, 1, 1, NULL, NULL, NULL
  113. };
  114.  
  115. Menu_Add(name, enabled)
  116.    char *name;
  117.    int enabled;
  118. {
  119.    register struct Menu *m;
  120.  
  121.    if ((Top = (struct Mem_Node *) AllocMem(
  122.          (LONG)sizeof(struct Mem_Node), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  123.       return NULL;
  124.    Top->mn_Node.ln_Type = NT_MEMORY;
  125.  
  126.    if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory),
  127.                  (LONG)sizeof (struct Menu), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  128.       return NULL;
  129.    Top->mn_Menu = m;
  130.  
  131.    if (LastMenu == NULL)
  132.       AutoMenu = m;     /* first menu on list */
  133.    else
  134.       LastMenu->NextMenu = m;      /* link it in */
  135.  
  136.    LastMenuItem = NULL;            /* end of previous MenuItem list */
  137.    LastSubItem = NULL;
  138.    Cur_MenuItem = Cur_SubItem = -1; /* reset item numbers */
  139.    if (LastMenu == NULL)
  140.       m->LeftEdge = 0;
  141.    else
  142.       m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width;
  143.    m->TopEdge = 0;
  144.    itd.IText = (UBYTE *)name;
  145.    m->Width = IntuiTextLength(&itd);
  146.    Top->mn_Node.ln_Name = m->MenuName = strsave(name);
  147.    m->Height = 0;
  148.    m->Flags = enabled ? MENUENABLED : 0;
  149.    m->FirstItem = NULL;
  150.    LastMenu = m;
  151.  
  152.    AddHead(&Memory, Top);
  153.    return MNUM(++Cur_Menu, NOITEM, NOSUB);
  154. }
  155.  
  156. /*
  157.  *  Add a menu item to the current MENU.  Note that Add_Menu *must* be
  158.  *  called before this function.
  159.  */
  160. Menu_Item_Add(name, flags, mux, ch)
  161.    char *name;       /* name of menu item */
  162.    USHORT flags;
  163.    LONG mux;         /* mutual exclusion mask */
  164.    BYTE ch;        /* command sequence character, if COMMSEQ */
  165. {
  166.    register struct MenuItem *m, *n;
  167.    register struct IntuiText *it;
  168.  
  169.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  170.    if (LastMenu == NULL)
  171.       return MNUM(NOMENU, NOITEM, NOSUB);
  172.  
  173.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  174.            (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  175.       return MNUM(NOMENU, NOITEM, NOSUB);
  176.  
  177.    LastSubItem = NULL;        /* terminate possible list of subitems */
  178.    Cur_SubItem = -1;
  179.    if (LastMenuItem == NULL)
  180.       LastMenu->FirstItem  = m;
  181.    else
  182.       LastMenuItem->NextItem = m;
  183.    m->Flags = flags | ITEMTEXT;
  184.    /*
  185.     *  Check for highlight mode:  if none selected, use HIGHCOMP
  186.     */
  187.    if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0)
  188.       m->Flags |= HIGHCOMP;
  189.    m->Command = ch;
  190.    m->MutualExclude = mux;
  191.    m->SubItem = NULL;
  192.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  193.                  (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  194.    it = (struct IntuiText *) m->ItemFill;
  195.    it->FrontPen = AUTOFRONTPEN;
  196.    it->BackPen = AUTOBACKPEN;
  197.    it->DrawMode = JAM2;
  198.    if (flags & CHECKIT)
  199.       it->LeftEdge = CHECKWIDTH + 1;
  200.    else
  201.       it->LeftEdge = 1;
  202.    it->TopEdge = 1;
  203.    it->ITextFont = NULL;      /* default font */
  204.    it->IText = (UBYTE *)strsave(name);
  205.    it->NextText = NULL;
  206.    if (LastMenuItem == NULL) {
  207.       m->TopEdge = 2;
  208.       m->LeftEdge = 0;
  209.    } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) {
  210.       m->TopEdge = 2;
  211.       m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12;
  212.       if (m->LeftEdge > SCREENWIDTH) {
  213.       LastMenuItem->NextItem = NULL;
  214.       LastMenuItem->Flags &= ~ITEMENABLED;
  215.             return MNUM(NOMENU, NOITEM, NOSUB);
  216.       }
  217.    } else {
  218.       m->TopEdge = LastMenuItem->TopEdge + 10;
  219.       m->LeftEdge = LastMenuItem->LeftEdge;
  220.    }
  221.    m->Width = 0;
  222.    if (flags & CHECKIT)
  223.       m->Width += CHECKWIDTH;
  224.    if (flags & COMMSEQ)
  225.       m->Width += COMMWIDTH + 20;
  226.    m->Width += IntuiTextLength(m->ItemFill);
  227.    m->Height = 10;
  228.    /*
  229.     *  Check last menu item's width to see if it is larger than this
  230.     *  item's.  If new item is larger, then update width of all other
  231.     *  items.
  232.     */
  233.    if (LastMenuItem) {
  234.       if (LastMenuItem->Width > m->Width)
  235.         m->Width = LastMenuItem->Width;
  236.       else {
  237.          register short delta = m->Width - LastMenuItem->Width;
  238.  
  239.      for (n = LastMenu->FirstItem; n != m; n = n->NextItem) {
  240.         n->Width = m->Width;
  241.         if (n->LeftEdge > 0) n->LeftEdge += delta;
  242.      }
  243.      if (m->LeftEdge > 0) m->LeftEdge += delta;
  244.       }
  245.    }
  246.    LastMenuItem = m;
  247.    return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB);
  248. }
  249.  
  250.  
  251.  
  252. Menu_SubItem_Add(name, flags, mux, ch)
  253.    char *name, ch;
  254.    USHORT flags;
  255.    LONG mux;
  256. {
  257.    register struct MenuItem *m, *n;
  258.    register struct IntuiText *it;
  259.  
  260.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  261.    if (LastMenuItem == NULL)
  262.       return MNUM(NOMENU, NOITEM, NOSUB);
  263.  
  264.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  265.            (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  266.       return MNUM(NOMENU, NOITEM, NOSUB);
  267.  
  268.    if (LastSubItem == NULL)
  269.       LastMenuItem->SubItem = m;
  270.    else
  271.       LastSubItem->NextItem = m;
  272.    m->Flags = flags | ITEMTEXT;
  273.    /*
  274.     * check for highlight mode.  If none selected, use HIGHCOMP
  275.     */
  276.    if ((m->Flags & (HIGHCOMP|HIGHBOX)) == 0)
  277.       m->Flags |= HIGHCOMP;
  278.    m->Command = ch;
  279.    m->MutualExclude = mux;
  280.    m->SubItem = NULL;
  281.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  282.                      (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  283.    it = (struct IntuiText *) m->ItemFill;
  284.    it->FrontPen = AUTOFRONTPEN;
  285.    it->BackPen = AUTOBACKPEN;
  286.    it->DrawMode = JAM2;
  287.    if (flags & CHECKIT)
  288.       it->LeftEdge = CHECKWIDTH + 1;
  289.    else
  290.       it->LeftEdge = 1;
  291.    it->TopEdge = 1;
  292.    it->ITextFont = NULL;      /* default font */
  293.    it->IText = (UBYTE *)strsave(name);
  294.    it->NextText = NULL;
  295.    m->LeftEdge = LastMenuItem->Width + 10;
  296.    m->Width = 0;
  297.    if (LastSubItem == NULL)
  298.       m->TopEdge = 1;
  299.    else
  300.       m->TopEdge = LastSubItem->TopEdge + 10;
  301.    if (flags & CHECKIT)
  302.       m->Width += CHECKWIDTH;
  303.    if (flags & COMMSEQ)
  304.       m->Width += COMMWIDTH + 20;
  305.    m->Width += IntuiTextLength(m->ItemFill);
  306.    m->Height = 10;
  307.    /*
  308.     *  Check last menu item's width to see if it is larger than this
  309.     *  item's.  If new item is larger, then update width of all other
  310.     *  items.
  311.     */
  312.    if (LastSubItem) {
  313.     if (LastSubItem->Width > m->Width)
  314.         m->Width = LastSubItem->Width;
  315.     else
  316.         for (n = LastMenuItem->SubItem; n != m; n = n->NextItem)
  317.         n->Width = m->Width;
  318.    }
  319.    LastSubItem = m;
  320.    return MNUM(Cur_Menu, Cur_MenuItem, ++Cur_SubItem);
  321. }
  322.  
  323. char *
  324. strsave(string) char *string; {
  325.    char *out ;
  326.  
  327.    out = (char *) AllocRemember(&(Top->mn_Memory), (LONG)(strlen(string) + 1),
  328.     MEMF_PUBLIC) ;
  329.    if (out == NULL) return NULL ;
  330.  
  331.    (void) strcpy(out, string) ;
  332.    return out ;
  333. }
  334.